
package com.baijia.commons.tianxiao;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baijia.commons.constant.Constant;
import com.baijia.commons.lang.utils.PropertiesReader;
import com.baijia.commons.lang.utils.http.HttpClientUtils;
import com.baijia.commons.util.EncryptUtils;
import com.baijia.commons.util.JacksonUtil;

/**
 * @title WrapTokenFromCookieFilter
 * @desc 从cookie中取出org_auth_token，解析后初始化TianXiaoContext
 * @author caoliang
 * @date 2015年12月1日
 * @version 1.0
 */
public class WrapOrgTokenFilter implements Filter {

    private static final String DEFAULTCOOKIENAME = "ORG_AUTH_TOKEN";
    private static final String DEFAULTPARAMNAME = "auth_token";
    private static final String DEFAULTPROPNAME = "passport-client.properties";
    private static final String DEFAULTVALIDTOKENURL = "valid.token.url";

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private String cookieName = DEFAULTCOOKIENAME;

    private String paramName = DEFAULTPARAMNAME;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // nothing to do
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        String encryptedToken = retrieveCookieValue(servletRequest);
        // 先从cookie找，没有找到从参数找，还没有就是没传。pc版做的时候，需要兼容pc的初始化。
        if (StringUtils.isNotBlank(encryptedToken)) {
//            if (!isValidAuthToken(encryptedToken)) {
//                JacksonUtil.writeObj(response.getOutputStream(), new AppBaseResponse("您的账户已经在其他设备登录", Constant.TOKEN_INVALID, null));
//                return;
//            }
            initTianxiaoContext(encryptedToken);
            if (logger.isDebugEnabled()) {
                logger.debug("initTianxiaoContext from cookie");
            }
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("can't find token in cookie. try find by request param");
            }
            encryptedToken = servletRequest.getParameter(paramName);
            if (StringUtils.isNotBlank(encryptedToken)) {
                if (!isValidAuthToken(encryptedToken)) {
                    JacksonUtil.writeObj(response.getOutputStream(), new AppBaseResponse("您的账户已经在其他设备登录", Constant.TOKEN_INVALID, null));
                    return;
                }
                initTianxiaoContext(encryptedToken);
                if (logger.isDebugEnabled()) {
                    logger.debug("initTianxiaoContext from request");
                }
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("can't find token in cookie and request.");
                }
            }
        }

        chain.doFilter(request, response);

        clearTianxiaoContext();
    }

    private boolean isValidAuthToken(String encryptedToken) {
        try {
            Properties prop = PropertiesReader.getProperties(DEFAULTPROPNAME);
            String url = prop.getProperty(DEFAULTVALIDTOKENURL);
            if (StringUtils.isNotBlank(url)) {
                Map<String, String> params = new HashMap<String, String>();
                params.put(DEFAULTPARAMNAME, encryptedToken);
                String json = HttpClientUtils.doPost(url, params);
                AppBaseResponse response = JacksonUtil.str2Obj(json, AppBaseResponse.class);
                if (!BooleanUtils.toBoolean(response.getData().toString())) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("valid auth_token fail.auth_token:{}", encryptedToken);
                    }
                    return false;
                }
            }
        } catch (Throwable e) {
            if (logger.isDebugEnabled()) {
                logger.debug("valid auth_token error", e);
            }
        }
        return true;
    }

    @Override
    public void destroy() {

    }

    protected String getCookieName() {
        return cookieName;
    }

    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }

    public String getParamName() {

        return paramName;
    }

    public void setParamName(String paramName) {

        this.paramName = paramName;
    }

    private void initTianxiaoContext(String encryptedToken) {
        try {
            OrgAppToken token = JacksonUtil.str2Obj(EncryptUtils.strDecode(encryptedToken), OrgAppToken.class);
            TianxiaoContext.setOrgId(token.getUser_id());
            TianxiaoContext.setOrgCascadeId(token.getCascade_user_id());
            TianxiaoContext.setOrgCascadeAuth(token.getAuth());
        } catch (Exception e) {
            logger.error("decode token error! encryptedToken is :" + encryptedToken, e);
        }
    }

    private String retrieveCookieValue(final HttpServletRequest request) {
        final Cookie cookie = org.springframework.web.util.WebUtils.getCookie(request, getCookieName());
        if (logger.isDebugEnabled()) {
            logger.info("get token from cookie | cookieName:{}, cookie value:{}", getCookieName(),
                cookie == null ? null : cookie.getValue());

        }
        return cookie == null ? null : cookie.getValue();
    }

    private void clearTianxiaoContext() {
        TianxiaoContext.clear();
    }

}
